using System;
using System.Drawing;
using System.Windows.Forms;
using System.Text;

namespace Meta.Editor
{
	/// <summary>
	/// Summary description for OutputWindow.
	/// </summary>
	public class OutputWindow  :  Meta.OutputWindow
	{
		ExRichTextBox tbox;
		RTextWriter writer;
		public OutputWindow() : base()
		{
			Text = "Output window";
			Size = new Size(640, 480);
			tbox = new ExRichTextBox();
			Controls.Add(tbox);
			writer = new RTextWriter(this);
		}

		public override SomewhatRichTextWriter TextWriter {
			get {
				return writer;
			}
		}

		public override bool WordWrap {
			get {
				return tbox.WordWrap;
			}
			set {
				tbox.WordWrap = value;
			}
		}

		protected override void OnLayout(LayoutEventArgs levent) {
			if (tbox!=null)
				tbox.Size = ClientSize;
			base.OnLayout (levent);
		}

		protected override void OnFontChanged(EventArgs e) {
			tbox.Font = Font;
			base.OnFontChanged (e);
		}


		class RTextWriter : Meta.SomewhatRichTextWriter {
			OutputWindow window;
			const int bufferSize = 50;

			char[] outputBuffer= new char[bufferSize+1];
			int bufferIndex=0;  // next position in buffer to be filled.

			public RTextWriter(OutputWindow w) {
				window = w;
			}

			public override void Flush() {
				if (bufferIndex>0)
					window.Invoke(new IShouldntHaveToDeclareThisEither(window.tbox.AppendText), new object[1] { new string(outputBuffer, 0, bufferIndex) });
				bufferIndex=0;
			}

			private delegate void IShouldntHaveToDeclareThis(System.Drawing.Image i);
			public override void Write(System.Drawing.Image i) {
				window.Invoke(new IShouldntHaveToDeclareThis(window.tbox.InsertImage), new object[1] {i});
			}
			private delegate void IShouldntHaveToDeclareThisEither(string s);

			//
			// Horrible kluge.
			// This is how we keep from inserting newline twice when doing control-enter in the listener.
			//
			public override void Write(string s) {
				foreach (char c in s) {
					outputBuffer[bufferIndex++] = c;
					if (bufferIndex>bufferSize)
						Flush();
				}
				//Flush();
				//window.Invoke(new IShouldntHaveToDeclareThisEither(window.WriteInternal), new object[1] {s});
			}

			delegate void ImSickOfThese(string s, System.Drawing.Font f);
			delegate void ImSickOfThese2(string s, System.Drawing.Font f, RtfColor c);
			public override void WriteStringInFont(string s, System.Drawing.Font f) {
				Flush();
				window.Invoke(new ImSickOfThese(window.tbox.AppendTextAsRtf), new object[] { s, f });
			}

			public void WriteStringInFont(string s, System.Drawing.Font f, RtfColor foreground)
			{
				Flush();
				window.Invoke(new ImSickOfThese2(window.tbox.AppendTextAsRtf), new object[] { s, f, foreground });
			}

			public override void Write(char c) {
				if (c=='\r')
					return;
				outputBuffer[bufferIndex++] = c;
				if (bufferIndex>bufferSize)
					Flush();
			}

			public override Encoding Encoding {
				get {
					return Encoding.Default;
				}
			}
			public override System.Drawing.Graphics CreateGraphics() {
				return window.CreateGraphics();
			}

			public override System.Drawing.Color GetBackColor() {
				return window.tbox.BackColor;
			}

			public override void UnindentEndOfBuffer() {
				return;
			}
		}
	}
}
